﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;


namespace PVFSLEAP
{
	class C_EVNT
	{
		F_SETT	ST = new F_SETT();
		C_NODE	ND = new C_NODE();
		C_PVFS	PV = new C_PVFS();
		C_COMM	CM = new C_COMM();

		SortedList SLCT = new SortedList();
		Hashtable PPLT = new Hashtable();

		Hashtable GNS0 = new Hashtable();
		Hashtable GNS1 = new Hashtable();
		Hashtable GNS2 = new Hashtable();
		Hashtable GNS3 = new Hashtable();
		Hashtable GNS4 = new Hashtable();
		Hashtable GNS5 = new Hashtable();
		Hashtable GNS6 = new Hashtable();
		Hashtable GNS7 = new Hashtable();

		Hashtable CRS0 = new Hashtable();
		Hashtable CRS1 = new Hashtable();

		//int[] CRS0 = new int[20];
		//int[] CRS1 = new int[20];

		Hashtable OFFS = new Hashtable();

		Random C = new Random( ( int )DateTime.Now.Millisecond % 999 );
		Random K = new Random( ( int )DateTime.Now.Millisecond % 999 );
		Random GARD = new Random( ( int )DateTime.Now.Millisecond );

		

		static int evnt = 0;

		public int chooseCH()
		{
			//System.Threading.Thread.Sleep( 1 );
			int c = C.Next( 1, 100 );
			return c;
		}

		public int getKey()
		{
			System.Threading.Thread.Sleep( 1 );
			int k = K.Next( 0, ST.OCHLD - 1 );
			return k;
		}

		public void attackFRIA( C_NODE[] SN )
		{
			evnt++;
			int chnd = -1;
			int ndid = -1;
			int mvid = -1;
			int tvfv = 0;

			int vote = 0;

			//chnd = chooseCH();
			while ( true )
			{
				chnd = chooseCH();
				if ( SN[chnd].CPNF == true )
					break;
			}

			PV.generateReport( chnd, SN );
			ndid = chnd;

			for ( int i=0; i < C_PVFS.vote.Count; i++ )
			{
				if ( C_PVFS.vote.GetByIndex(i).ToString() == "T" )
					vote++;
			}

			if ( ( vote != 0 ) && ( vote < ST.OTVFV ) )
				SN[chnd].OFVI++;
			else if ( vote == ST.OTVFV )
				SN[chnd].OFRI++;

			//int numk = PV.generateKeys();
			//for ( int i = 0; i < numk; i++ )
			//{
			//SN[chnd].ENGY = CM.consumeTransmitting( SN[chnd].ENGY, 8 * numk );
			//SN[chnd].ENGY = CM.consumeReceiving( SN[chnd].ENGY, 8 * numk );
			//}

			// Population Set based Genetic Algorithm
			if ( ST.OGNTC == 1 )
			{
				PPLT.Clear();
				GNS0.Clear();
				GNS1.Clear();
				GNS2.Clear();
				GNS3.Clear();
				GNS4.Clear();
				GNS5.Clear();
				GNS6.Clear();
				GNS7.Clear();

				CRS0.Clear();
				CRS1.Clear();

				SLCT.Clear();
				OFFS.Clear();

				while ( true )
				{
					mvid = SN[ndid].PRID;
                    //int ec = getEnergyLevel( SN[mvid].ENGY );

                    //SN[mvid].GNTC[0] = ec;
                    //SN[mvid].GNTC[1] = SN[mvid].DFVI;
                    //SN[mvid].GNTC[2] = SN[mvid].HPCT;

                    //SN[mvid].FTNS = FL.fuzzy( SN[mvid].GNTC[0], SN[mvid].GNTC[1], SN[mvid].GNTC[2] );
                    //PPLT.Add( mvid, SN[mvid].FTNS );

					if ( SN[mvid].NDID == 0 )
							break;

					ndid = mvid;
				}

				for ( int i = 0; i <= 7; i++ )
				{
					switch ( i )
					{
						case 0:
							makeGenes( chnd, SN, PPLT, GNS0 );
							makeSelection( i, PPLT, GNS0 );
							break;
						case 1:
							makeGenes( chnd, SN, PPLT, GNS1 );
							makeSelection( i, PPLT, GNS1 );
							break;
						case 2:
							makeGenes( chnd, SN, PPLT, GNS2 );
							makeSelection( i, PPLT, GNS2 );
							break;
						case 3:
							makeGenes( chnd, SN, PPLT, GNS3 );
							makeSelection( i, PPLT, GNS3 );
							break;
						case 4:
							makeGenes( chnd, SN, PPLT, GNS4 );
							makeSelection( i, PPLT, GNS4 );
							break;
						case 5:
							makeGenes( chnd, SN, PPLT, GNS5 );
							makeSelection( i, PPLT, GNS5 );
							break;
						case 6:
							makeGenes( chnd, SN, PPLT, GNS6 );
							makeSelection( i, PPLT, GNS6 );
							break;
						case 7:
							makeGenes( chnd, SN, PPLT, GNS7 );
							makeSelection( i, PPLT, GNS7 );
							break;
					}
				}

				while ( true )
				{
					if ( SLCT.Count <= 2 )
					{
						int gene = ( int )SLCT.GetKey( SLCT.Count - 1 );
						makeCrossover( 2, gene );
						crossoverNothing( CRS0 );
						makeMutation( OFFS );
					}
					else
					{
						int gen1 = ( int ) SLCT.GetKey( SLCT.Count - 1 );
						int gen2 = ( int ) SLCT.GetKey( SLCT.Count - 2 );

						makeCrossover( 0, gen1 );
						makeCrossover( 1, gen2 );

						crossoverOnePoint( CRS0, CRS1 );

						makeMutation( OFFS );

						makeSelection( SLCT.Count, PPLT, OFFS );
					}

					


				    if ( OFFS.Count >= 0 )
				        break;
				}
			}

			tagVerification( SN , OFFS );

			ndid = chnd;
			while ( true )
			{
				mvid = SN[ndid].PRID;

				if ( SN[mvid].NDID == 0 )
					break;

				SN[ndid].ENGY = CM.consumeReceiving( SN[ndid].ENGY, 24 );
				
				if ( ST.OGNTC == 1 )
				{
					if ( SN[ndid].VRND == true )
					{
						int numk = PV.generateKeys();

						for ( int i = 0; i < SN[chnd].HPCT - SN[mvid].HPCT; i++ )
						{
							//SN[mvid].ENGY = CM.consumeTransmitting( SN[mvid].ENGY, numk * 1 );
							//SN[mvid].ENGY = CM.consumeReceiving( SN[mvid].ENGY, numk * 1 );
						}

						for ( int i = 0; i < numk; i++ )
						{
							int keys = getKey();

							if ( C_PVFS.vote.Contains( keys ) == true )
							{
								if ( C_PVFS.vote[keys].ToString() == "T" )
								{
									if ( vote == 1 )
										SN[mvid].DFVI++;

									tvfv++;
									C_PVFS.vote[keys] = "F";
									break;
								}
							}
						}
					}

					if ( tvfv >= ST.OTVFV )
					{
						SN[mvid].DFRI++;
						break;
					}

					SN[mvid].ENGY = CM.consumeTransmitting( SN[mvid].ENGY, 24 );
					ndid = mvid;
				}
				else
				{
					if ( ST.OPVFS == C_COMM.TRUE )
					{
						if ( ST.OFZZY != C_COMM.TRUE )
						{
							if ( PV.checkVerifiedNode( SN[mvid].HPCT, SN[chnd].HPCT ) == true )
							{
								int numk = PV.generateKeys();
						
								for ( int i = 0; i < SN[chnd].HPCT - SN[mvid].HPCT; i++ )
								{
									//SN[mvid].ENGY = CM.consumeTransmitting( SN[mvid].ENGY, numk * 1 );
									//SN[mvid].ENGY = CM.consumeReceiving( SN[mvid].ENGY, numk * 1 );
								}

								for ( int i = 0; i < numk; i++ )
								{
									int keys = getKey();

									if ( C_PVFS.vote.Contains( keys ) == true )
									{
										if ( C_PVFS.vote[ keys ].ToString() == "T" )
										{
											if ( vote == 1 )
												SN[mvid].DFVI++;

											tvfv++;
											C_PVFS.vote[keys] = "F";
											break;
										}
									}
								}
							}
						}
						else
						{
                            //float flag = 0.0f;
                            //int dst = 0;
                            //int nfv = 0;

                            //dst = (SN[chnd].HPCT / SN[chnd].HPCT)*100;

                            //if ( SN[mvid].DFVI >= 20 )
                            //    nfv = 20;

                            //flag = FL.fuzzy( getEnergyLevel( SN[mvid].ENGY ), 
                            //                 dst, 
                            //                 nfv );

							if ( PV.checkVerifiedNode( SN[mvid].HPCT, SN[chnd].HPCT ) == true )
							{
								int numk = PV.generateKeys();

								for ( int i = 0; i < SN[chnd].HPCT - SN[mvid].HPCT; i++ )
								{
									//SN[mvid].ENGY = CM.consumeTransmitting( SN[mvid].ENGY, numk * 1 );
									//SN[mvid].ENGY = CM.consumeReceiving( SN[mvid].ENGY, numk * 1 );
								}

								for ( int i = 0; i < numk; i++ )
								{
									int keys = getKey();

									if ( C_PVFS.vote.Contains( keys ) == true )
									{
										if ( C_PVFS.vote[keys].ToString() == "T" )
										{
											if ( vote == 1 )
												SN[mvid].DFVI++;

											tvfv++;
											C_PVFS.vote[keys] = "F";
											break;
										}
									}
								}
							}
						}

					}
					else if ( ST.OPPMT == C_COMM.TRUE )
					{
						if ( ndid == chnd )
						{
							for ( int i=0; i < C_PVFS.vote.Count; i++ )
							{
								if ( C_PVFS.vote.GetByIndex(i).ToString() == "T" )
								{
									if ( vote == 1 )
										SN[mvid].DFVI++;

									C_PVFS.vote[C_PVFS.vote.GetKey(i)] = "F";
									tvfv++;
								}
							}
						}
					}

					if ( tvfv >= ST.OTVFV )
					{
						SN[mvid].DFRI++;
						break;
					}

					if ( SN[mvid].NDID == 0 )
						break;

					SN[mvid].ENGY = CM.consumeTransmitting( SN[mvid].ENGY, 24 );
					ndid = mvid;	
				}				
			}
		}

		// Verification Node Decision
		public void tagVerification( C_NODE[] SN , Hashtable OF )
		{
			double fsum = 0.0f;
			double favg = 0.0f;

			int vcnt = 0;
			IDictionaryEnumerator FF = OF.GetEnumerator();
			IDictionaryEnumerator SM = OF.GetEnumerator();

			while( SM.MoveNext() )
			{
				fsum += SN[( int )SM.Key].FTNS;
				vcnt++;
			}

			favg = fsum / vcnt;

			vcnt = 0;

			while( FF.MoveNext() )
			{
				if ( vcnt < OF.Count / 2 )
				{
					if ( ( SN[( int )FF.Key].FTNS > favg ) )
					{
						if ( FF.Value.ToString() == "T" )
							SN[(int)FF.Key].VRND = true;
						vcnt++;
					}
				}
				

				//else if ( evnt < 100 )
				//{
				//    if ( ( SN[( int )FF.Key].FTNS >= 2 ) )
				//    {
				//        if ( FF.Value.ToString() == "T" )
				//            SN[( int )FF.Key].VRND = true;
				//    }
				//}
				//else if ( evnt < 150 )
				//{
				//    if ( ( SN[( int )FF.Key].FTNS >= 4 ) )
				//    {
				//        if ( FF.Value.ToString() == "T" )
				//            SN[( int )FF.Key].VRND = true;
				//    }
				//}
				//else if ( evnt < 200 )
				//{
				//    if ( ( SN[( int )FF.Key].FTNS >= 4 ) )
				//    {
				//        if ( FF.Value.ToString() == "T" )
				//            SN[( int )FF.Key].VRND = true;
				//    }
				//}
				//else if ( evnt < 250 )
				//{
				//    if ( ( SN[( int )FF.Key].FTNS >= 6 ) )
				//    {
				//        if ( FF.Value.ToString() == "T" )
				//            SN[( int )FF.Key].VRND = true;
				//    }
				//}
				
			}
		}

		public void copyOFFS( Hashtable SL )
		{
			OFFS.Clear();

			IDictionaryEnumerator SS = SL.GetEnumerator();

			while ( SS.MoveNext() )
				OFFS.Add( SS.Key, SS.Value );
		}

		public void makeGenes( int chnd, C_NODE[] SN, Hashtable PP, Hashtable GN)
		{
			IDictionaryEnumerator PL = PP.GetEnumerator();

			while ( PL.MoveNext() )
			{
				if ( (int )PL.Key != 0 )
				{
					int mvid = ( int ) PL.Key;
					GN.Add( mvid, PV.makeVerifiedNode( SN[mvid].HPCT, SN[chnd].HPCT ) );
				}
			}			
		}

		public void makeSelection( int indx, Hashtable PP, Hashtable GN )
		{
			SLCT.Clear();

			double dsum = 0.0f;
			IDictionaryEnumerator PL = PP.GetEnumerator();
			IDictionaryEnumerator GS = GN.GetEnumerator();

			while ( PL.MoveNext() )
			{
				if ( GS.MoveNext() == false )
					break;

				if ( string.Format( "{0}", GS.Value ) == "T" )
				{
					dsum += double.Parse( string.Format( "{0}", PL.Value ) );
				}
			}

			SLCT.Add( indx, dsum );
		}

		public void makeCrossover( int flag, int indx )
		{
			if ( flag == 0 )
			{
				switch ( indx )
				{
					case 0:
						makeCrossover0( indx, GNS0 );
						break;
					case 1:
						makeCrossover0( indx, GNS1 );
						break;
					case 2:
						makeCrossover0( indx, GNS2 );
						break;
					case 3:
						makeCrossover0( indx, GNS3 );
						break;
					case 4:
						makeCrossover0( indx, GNS4 );
						break;
					case 5:
						makeCrossover0( indx, GNS5 );
						break;
					case 6:
						makeCrossover0( indx, GNS6 );
						break;
					case 7:
						makeCrossover0( indx, GNS7 );
						break;
				}
			}
			else if ( flag == 1 )
			{
				switch ( indx )
				{
					case 0:
						makeCrossover1( indx, GNS0 );
						break;
					case 1:
						makeCrossover1( indx, GNS1 );
						break;
					case 2:
						makeCrossover1( indx, GNS2 );
						break;
					case 3:
						makeCrossover1( indx, GNS3 );
						break;
					case 4:
						makeCrossover1( indx, GNS4 );
						break;
					case 5:
						makeCrossover1( indx, GNS5 );
						break;
					case 6:
						makeCrossover1( indx, GNS6 );
						break;
					case 7:
						makeCrossover1( indx, GNS7 );
						break;
				}
			}
			else
			{
				makeCrossover0( indx, GNS0 );
			}
		}

		public void makeCrossover0( int gene, Hashtable GN )
		{
			CRS0.Clear();
			IDictionaryEnumerator GS = GN.GetEnumerator();

			while ( GS.MoveNext() )
				CRS0.Add( ( int )GS.Key, GS.Value );
		}

		public void makeCrossover1( int gene, Hashtable GN )
		{
			CRS1.Clear();
			IDictionaryEnumerator GS = GN.GetEnumerator();

			while ( GS.MoveNext() )
				CRS1.Add( ( int )GS.Key, GS.Value );
		}

		public void crossoverOnePoint( Hashtable R1, Hashtable R2 )
		{
			int indx = 0;
			IDictionaryEnumerator C2 = R1.GetEnumerator();
			IDictionaryEnumerator C1 = R2.GetEnumerator();

			int i = GARD.Next(0, chooseMinium() );

			while( C1.MoveNext() )
			{
				C2.MoveNext();

				if ( OFFS.ContainsKey( C2.Key ) == false )
				{
					if( i >= indx )
						OFFS.Add( C2.Key, C2.Value );
					else
						OFFS.Add( C1.Key, C1.Value );
				}
				indx++;
			}
		}

		public void crossoverNothing( Hashtable R1 )
		{
			OFFS.Clear();
			IDictionaryEnumerator CR = R1.GetEnumerator();

			while( CR.MoveNext() )
				OFFS.Add( CR.Key, CR.Value );
		}

		public int chooseMinium()
		{
			if ( CRS0.Count < CRS1.Count )
				return CRS0.Count;
			else
				return CRS1.Count;
		}

		public int chooseCrossover()
		{
			if ( CRS0.Count < CRS1.Count )
				return 0;
			else
				return 1;
		}

		public void makeMutation( Hashtable RS )
		{
			int indx = 0;
			IDictionaryEnumerator RL = RS.GetEnumerator();
			int i = GARD.Next( 0, 99 );

			if ( i == 0 )
			{
				try
				{
					int n = GARD.Next( 0, OFFS.Count - 1);

					while( RL.MoveNext() )
					{
						if ( n == indx )
						{
							if ( RL.Value.ToString() == "T" )
								OFFS[RL.Key] = "F";
							else
								OFFS[RL.Key] = "T";
						}
						indx++;
					}
				}
				catch
				{
					return;
				}
			}
		}

		public int countVerificationNodes( Hashtable RS )
		{
			int vcnt = 0;
			IDictionaryEnumerator RL = RS.GetEnumerator();

			while( RL.MoveNext() )
			{
				if (RL.Value.ToString() == "T" )
					vcnt++;
			}

			return vcnt;
		}

		public void attackWormhole( C_NODE[] SN )
		{
			if ( ( ST.OLEAP == C_COMM.TRUE ) || ( ST.PPMT == C_COMM.TRUE ) )
			{
				for ( int i = 1; i < ST.OTTND; i++ )
				{
					if ( SN[i].WORM == true )
					{
						//for ( int c = 0; c < ST.OCHLD; c++ )
						//{
							double engy = CM.consumeReceiving( SN[i].ENGY, 1 );
							SN[i].ENGY = engy * ST.OCHLD;
							SN[i].OWRM++;
							SN[i].DWRM++;
							engy = CM.consumeTransmitting( SN[i].ENGY, 1 );
							SN[i].ENGY = engy * ST.OCHLD;
						//}
					}
				}
			}
		}
	}
}
